/* ws2812b.c */

#include "ws2812b.h"

#define WS2812B_DATA_BIT_COUNT_MAX  24U

#if 0
#define DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX  0U

#define DEMO_LPIT_WS2812B_BIT_START_COUNT_INDEX 0U
#define DEMO_LPIT_WS2812B_BIT_0_COUNT_INDEX     1U
#define DEMO_LPIT_WS2812B_BIT_1_COUNT_INDEX     2U
#define DEMO_LPIT_WS2812B_BIT_COUNT_MAX         3U
#endif

#define BSP_WS2812B_LED_COUNT 3U

#if 0
struct
{
    uint32_t LedData1[BSP_WS2812B_LED_COUNT]; /* 存放多个灯珠颜色数据 */
    uint32_t LedData2[BSP_WS2812B_LED_COUNT]; /* 存放多个灯珠颜色数据 */
    uint8_t  CurLedDataIndex; /* 当前操作哪个灯珠 */
    uint8_t  CurLedDataBitIndex; /* 当前灯珠颜色数据的哪一位 */

    void (*UpdateDoneCallbackFunc)(); /*更新完毕后执行回调函数*/

    uint8_t CurTimerUnitCounter; /* 中断内部的周期计数器 */
} gAppWs2812bInfoStruct;
#endif

void WS2812B_Init(void)
{
    //LPIT_ChannelConfig_T lpitChannelConfigStruct;

    /* 清零状态信息 */
    //memset(&gAppWs2812bInfoStruct, 0, sizeof(gAppWs2812bInfoStruct));

    /* 初始化引脚 */
    BSP_InitWs2812bGpio();
    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false); /* 低电平 */
    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT , BSP_GPIO_WS2812B_LEFT_PIN , false); /* 低电平 */
    GPIO_SetPinDir(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true); /* 输出 */
    GPIO_SetPinDir(BSP_GPIO_WS2812B_LEFT_PORT , BSP_GPIO_WS2812B_LEFT_PIN , true); /* 输出 */
#if 0
    /*
     * 配置LPIT.
     */
    /* Enable clock. */
    PCC->CLKCFG[PCC_LPIT0_INDEX] = PCC_CLKCFG_CGC_MASK | PCC_CLKCFG_PCS(6U); /* SPLL_CLK, PLLDIV2_CLK. */

    /* LPIT. */
    LPIT_HAL_Enable(LPIT0, true);
    LPIT_HAL_Reset(LPIT0);
    LPIT_HAL_GetChannelConfigForNormalTimer(&lpitChannelConfigStruct);

    LPIT_HAL_StopChannel(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);
    LPIT_HAL_ConfigChannel(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX, &lpitChannelConfigStruct);
    //LPTI_HAL_SetChannelTimeoutValue(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX, BSP_CLK_SPLLDIV2_HZ/2400000); /* 超时频率为2.4MHz. */
    LPIT_HAL_EnableChannelInterrupt(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX, true);

    /* NVIC. */
    NVIC_EnableIRQ(LPIT0_IRQn);
#endif
}

#if 0
volatile bool     gWs2812bLpitDelayDoneFlag;
volatile uint32_t gWs2812bLpitDelayDoneCount;
volatile uint32_t gDummy;


#define DEMO_WS2812B_FAST_DELAY_TICKS  (BSP_CLK_SPLLDIV2_HZ/2400000) /* 2400000 */
#define DEMO_WS2812B_SLOW_DELAY_TICKS  (BSP_CLK_SPLLDIV2_HZ/1200000) /* 1200000 */


/* 使用硬件定时器精确延时
* 传入参数为定时器的计数滴答值，也就是超时溢出的时间
*/
void WS2812B_DelayLpitTicks(uint32_t period_ticks)
{
    volatile uint32_t i;
    if (period_ticks == DEMO_WS2812B_FAST_DELAY_TICKS)
    {
        for (i = 0U; i < 2U; i++)
        {
            __NOP();
        }
    }
    else if (period_ticks == DEMO_WS2812B_SLOW_DELAY_TICKS)
    {
        for (i = 0U; i < 10U; i++)
        {
            __NOP();
        }
    }

#if 0
    gWs2812bLpitDelayDoneFlag = false;

    /* 设定超时 */
    LPTI_HAL_SetChannelTimeoutValue(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX, period_ticks);
    /* 启动定时器 */
    LPIT_HAL_StartChannel(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);
    /* 等待超时中断触发 */
    while (!gWs2812bLpitDelayDoneFlag)
    {}
#endif
}

void WS2812B_DelaySlow(void)
{
    volatile uint32_t i = 20;

    while (i--);
}

void WS2812B_DelayFast(void)
{
    volatile uint32_t i = 10;

    while (i--);
}

#endif

void WS2812B_DoUpdateColorRight(uint32_t color)
{
    uint32_t i, ledCount;

    //gWs2812bLpitDelayDoneCount = 0U;
    for (ledCount = 0U; ledCount < BSP_WS2812B_LED_COUNT; ledCount++)
    {
        for (i = 0U; i < WS2812B_DATA_BIT_COUNT_MAX; i++)
        {
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
        }
    }
}

void WS2812B_DoUpdateColorLeft(uint32_t color)
{
    uint32_t i, ledCount;

    //gWs2812bLpitDelayDoneCount = 0U;
    for (ledCount = 0U; ledCount < BSP_WS2812B_LED_COUNT; ledCount++)
    {
        for (i = 0U; i < WS2812B_DATA_BIT_COUNT_MAX; i++)
        {
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
        }
    }
    //printf("gWs2812bLpitDelayDoneCount: %d\r\n", gWs2812bLpitDelayDoneCount);
}
#if 0
void LPIT0_IRQHandler(void)
{
    if (LPIT_HAL_GetChannelTimeoutFlag(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX))
    {
        LPTI_HAL_ClearChannelTimeoutFlag(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);
        LPIT_HAL_StopChannel(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);
        gWs2812bLpitDelayDoneFlag = true;
        gWs2812bLpitDelayDoneCount++;
    }
}

bool WS2812B_SetLedColorData1(uint32_t *colors, uint32_t len)
{
    uint32_t i;

    if (len >= BSP_WS2812B_LED_COUNT)
    {
        return false;
    }

    for (i = 0U; i < BSP_WS2812B_LED_COUNT; i++)
    {
        gAppWs2812bInfoStruct.LedData1[i] = colors[i];
    }

    return true;
}

bool WS2812B_SetLedColorData2(uint32_t *colors, uint32_t len)
{
    uint32_t i;

    if (len >= BSP_WS2812B_LED_COUNT)
    {
        return false;
    }

    for (i = 0U; i < BSP_WS2812B_LED_COUNT; i++)
    {
        gAppWs2812bInfoStruct.LedData2[i] = colors[i];
    }

    return true;
}

void WS2812B_DoUpdateColor(void (*callback)(void))
{
    /* 保存回调函数 */
    gAppWs2812bInfoStruct.UpdateDoneCallbackFunc = callback;
    gAppWs2812bInfoStruct.CurLedDataIndex = 0U;
    gAppWs2812bInfoStruct.CurLedDataBitIndex = 0U;
    gAppWs2812bInfoStruct.CurTimerUnitCounter = 0U;

    /* 拉高控制信号，准备传输数据 */
    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);

    /* 启动定时器 */
    LPIT_HAL_StartChannel(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);
}

/* LPIT0中断服务程序 */
void LPIT0_IRQHandler(void)
{
    /* 查看标志 */
    if (LPIT_HAL_GetChannelTimeoutFlag(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX))
    {
        LPTI_HAL_ClearChannelTimeoutFlag(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);

        if (gAppWs2812bInfoStruct.CurTimerUnitCounter == DEMO_LPIT_WS2812B_BIT_COUNT_MAX)
        {
            gAppWs2812bInfoStruct.CurTimerUnitCounter = 0U;
        }
        else
        {
            gAppWs2812bInfoStruct.CurTimerUnitCounter++;
        }

        switch (gAppWs2812bInfoStruct.CurTimerUnitCounter)
        {
            case DEMO_LPIT_WS2812B_BIT_0_COUNT_INDEX: /* Create falling edge for bit value 0. */
                /* LED1 bit 0. */
                if (0U == (gAppWs2812bInfoStruct.LedData1[gAppWs2812bInfoStruct.CurLedDataIndex] & (1U << gAppWs2812bInfoStruct.CurLedDataBitIndex)))
                {
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                }
                /* LED2 bit 0. */
                if (0U == (gAppWs2812bInfoStruct.LedData2[gAppWs2812bInfoStruct.CurLedDataIndex] & (1U << gAppWs2812bInfoStruct.CurLedDataBitIndex)))
                {
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                }
                break;
            case DEMO_LPIT_WS2812B_BIT_1_COUNT_INDEX: /* Create falling edge for bit value 1. */
                /* LED1 bit 1. */
                if (0U != (gAppWs2812bInfoStruct.LedData1[gAppWs2812bInfoStruct.CurLedDataIndex] & (1U << gAppWs2812bInfoStruct.CurLedDataBitIndex)))
                {
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                }
                /* LED2 bit 1. */
                if (0U != (gAppWs2812bInfoStruct.LedData2[gAppWs2812bInfoStruct.CurLedDataIndex] & (1U << gAppWs2812bInfoStruct.CurLedDataBitIndex)))
                {
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                }
                break;
            default: /* DEMO_LPIT_WS2812B_BIT_START_COUNT_INDEX */
                /* 判断结束条件 */
                if (gAppWs2812bInfoStruct.CurLedDataIndex < BSP_WS2812B_LED_COUNT)
                {
                    /* 拉高信号线，准备传输下一个颜色bit的数据 */
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                    gAppWs2812bInfoStruct.CurLedDataBitIndex++;
                    if ()
                }
                else
                {
                    /* 停止传输过程 */
                    LPIT_HAL_StopChannel(LPIT0, DEMO_LPIT_WS2812B_REFRESH_CHANNEL_INDEX);

                    /* 拉低信号线，进入idle状态 */
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);

                    /* 执行用户回调函数 */
                    if (NULL != gAppWs2812bInfoStruct.UpdateDoneCallbackFunc)
                    {
                        (*(gAppWs2812bInfoStruct.UpdateDoneCallbackFunc))();
                        gAppWs2812bInfoStruct.UpdateDoneCallbackFunc = NULL;
                    }
                }
                break;
        }

    }
}

#endif

